#include "application.h"
#include <Arduino.h>
#include "mtime.h"
#include "display.h"
#include <Ticker.h>
#include "animations.h"
#include "audio.h"
#include "weather.h"
#include "aht20.h"

Ticker my_ticker;
static bool need_sys_time_sync = false; // 初始化时已经同步过了
void ticker_cb_10min()
{
  need_sys_time_sync = true;
  Serial.println("syn time once");
}

void mode_init()
{
  my_ticker.attach(10 * 60, ticker_cb_10min);
}

static unsigned long update_time_last_time = 0;
static bool flag_show_colon = true;
static char s_hour[10] = {};
static char s_min[10] = {};
static char s_sec[10] = {};
void show_time(bool need_sync)
{
  if (need_sync)
  {
    need_sys_time_sync = false;
    sync_sys_time();
  }

  if (millis() - update_time_last_time > INTERVAL_UPDATE_TIME || update_time_last_time == 0)
  {
    struct tm timeinfo;
    if (!getLocalTime(&timeinfo))
    {
      Serial.println("Failed to obtain time");
      return;
    }
    sprintf(s_hour, "%02d", timeinfo.tm_hour);
    sprintf(s_min, "%02d", timeinfo.tm_min);
    sprintf(s_sec, "%02d", timeinfo.tm_sec);
    update_time_last_time = millis();

    flag_show_colon = !flag_show_colon;
  }
  char tmp[20] = {};
  sprintf(tmp, "%s %s %s", s_hour, s_min, s_sec);
  anim_time(tmp, flag_show_colon);
}

static unsigned long update_date_last_time = 0;
static char s_year[10] = {};
static char s_month[10] = {};
static char s_day[10] = {};
static char s_week[2] = {};
// 2种写法
// 1.  if (millis() - show_raining_last_time > INTERVAL_ANIM_RAINING)
// 2.如下
int show_date_anim_interval_n = INTERVAL_ANIM_CNT_INIT_VALUE;
void show_date(bool need_sync)
{
  if (need_sync)
  {
    need_sys_time_sync = false;
    sync_sys_time();
  }

  if (millis() - update_date_last_time > INTERVAL_UPDATE_DATE || update_date_last_time == 0) // 或者在初始化时更新一次
  {
    struct tm timeinfo;
    if (!getLocalTime(&timeinfo))
    {
      Serial.println("Failed to obtain time");
      return;
    }
    sprintf(s_year, "%02d", timeinfo.tm_year + 1900);
    sprintf(s_month, "%02d", timeinfo.tm_mon + 1);
    sprintf(s_day, "%02d", timeinfo.tm_mday);
    if (timeinfo.tm_wday == 0)
      sprintf(s_week, "7");
    else
      sprintf(s_week, "%d", timeinfo.tm_wday);
    update_date_last_time = millis();
  }

  show_date_anim_interval_n++;
  if (show_date_anim_interval_n % INTERVAL_ANIM_MULTIPLIER_DATE != 0)
    return;

  char tmp[24] = {};
  sprintf(tmp, "%s  %s  %s", s_year, s_month, s_day);
  char tmp2[4] = {};
  sprintf(tmp2, " W%s", s_week);

  anim_date(tmp, tmp2);

  show_date_anim_interval_n = 0;
}

int show_raining_anim_interval_n = INTERVAL_ANIM_CNT_INIT_VALUE;
void show_raining_code()
{
  show_raining_anim_interval_n++;
  if (show_raining_anim_interval_n % INTERVAL_ANIM_MULTIPLIER_RAINING != 0)
    return;

  anim_raining_code();
  show_raining_anim_interval_n = 0;
}

int show_audio_spectrum_interval_n = INTERVAL_ANIM_CNT_INIT_VALUE;
void show_audio_spectrum()
{
  show_audio_spectrum_interval_n++;
  if (show_audio_spectrum_interval_n % INTERVAL_ANIM_MULTIPLIER_AUDIO_SPECTRUM != 0)
    return;
  audio_spectrum_anim();
  show_raining_anim_interval_n = 0;
}

// 在全局变量区添加
timer_state_t timer_5min;                                 // 初始未运行，总时长5分钟
int show_timer_interval_n = INTERVAL_ANIM_CNT_INIT_VALUE; // 动画更新计数器
void show_timer()
{
  show_timer_interval_n++;
  if (show_timer_interval_n % INTERVAL_ANIM_MULTIPLIER_TIMER != 0)
    return;
  bool finished = anim_timer(&timer_5min);
  if (finished)
  {
    audio_max98357_mp3_play(MP3_URL_TIMER_FINISH, false);
  }

  show_timer_interval_n = 0;
}

int show_weather_interval_n = -1;
unsigned long update_weather_last_time = 0;
int show_weather_idx = 0;
int show_weather_tick_n = 0;
void show_weather()
{
  show_weather_interval_n++;
  if (show_weather_interval_n % INTERVAL_ANIM_MULTIPLIER_WEATHER != 0)
    return;

  static weather_info_t we;
  if (millis() - update_weather_last_time > INTERVAL_UPDATE_WEATHER || update_weather_last_time == 0) // 或者在初始化时更新一次
  {
    we = get_forecast_weather("HangZhou");
    update_weather_last_time = millis();
  }
  show_weather_tick_n++;
  bool need_init = false;
  if (show_weather_tick_n > 30) // 每个只显示30*INTERVAL_ANIM_MULTIPLIER_WEATHER个tick，实际是60个
  {
    show_weather_idx++;
    show_weather_tick_n = 0;
    need_init = true;
  }

  if (show_weather_idx >= 3) // 循环
  {
    show_weather_idx = 0;
  }

  // Serial.printf("weather: %s\n", we.weathers[0].text);
  anim_weather(&(we.weathers[show_weather_idx]), show_weather_idx, need_init);

  show_weather_interval_n = 0;
}

int show_aht20_interval_n = INTERVAL_ANIM_CNT_INIT_VALUE;
void show_aht20()
{
  show_aht20_interval_n++;
  if (show_aht20_interval_n % INTERVAL_ANIM_MULTIPLIER_AHT20 != 0)
    return;

  aht20_result_t res = aht20_get_result();

  anim_aht20(res.temperature, res.humidity);

  show_aht20_interval_n = 0;
}

///////////////////////////////
ModeType old_mode;
void mode_select(ModeType m)
{
  switch (m)
  {
  case MODE_TIME:
    show_time(need_sys_time_sync);
    break;
  case MODE_DATE:
    show_date(need_sys_time_sync);
    break;
  case MODE_ANIM_RAINING:
    show_raining_code();
    break;
  case MODE_AUDIO_SPECTURM:
    show_audio_spectrum();
    break;
  case MODE_TIMER_5MIN:
    if (old_mode != MODE_TIMER_5MIN)
      timer_state_init(&timer_5min, 300);// 300s
    show_timer();
    break;
  case MODE_WEATHER:
    show_weather();
    break;
  case MODE_AHT20:
    show_aht20();
    break;
  default:
    break;
  }

  old_mode = m;
}

CRGB oldLeds[MATRIX_NUM_LEDS]; // 声明临时LED缓冲区
CRGB newLeds[MATRIX_NUM_LEDS]; // 声明临时LED缓冲区
void switch_mode(ModeType m)
{
  if (old_mode != m)
  {
    Serial.printf("mode changed from %d to %d\r\n", old_mode, m);

    // 模式切换后重置状态
    update_time_last_time = 0;
    update_date_last_time = 0;
    update_weather_last_time = 0;
    // 动画重置
    show_date_anim_interval_n = INTERVAL_ANIM_CNT_INIT_VALUE;
    show_raining_anim_interval_n = INTERVAL_ANIM_CNT_INIT_VALUE;
    show_audio_spectrum_interval_n = INTERVAL_ANIM_CNT_INIT_VALUE;
    show_timer_interval_n = INTERVAL_ANIM_CNT_INIT_VALUE;
    show_weather_interval_n = INTERVAL_ANIM_CNT_INIT_VALUE;
    show_aht20_interval_n = INTERVAL_ANIM_CNT_INIT_VALUE;
    show_weather_idx = 0;
    show_weather_tick_n = 0;
    anim_init();
    audio_max98357_mp3_stop();

#ifdef SWITCH_MODE_ANIM_ENABLE
    if (m != MODE_TIMER_5MIN) // 定时器模式不需要切换动画
    {
      // 执行从右到左滑动动画
      // 使用Adafruit_GFX实现从右到左滑动动画
      // 保存旧画面位图
      memcpy(oldLeds, _leds, MATRIX_NUM_LEDS * sizeof(CRGB));

      // 绘制新画面到位图
      displayManager->SetShowEnable(false);
      // 根据新模式绘制内容
      mode_select(m);

      // 获取新画面位图
      memcpy(newLeds, _leds, MATRIX_NUM_LEDS * sizeof(CRGB));
      displayManager->SetShowEnable(true);

      // 执行滑动动画
      for (int16_t offset = 0; offset <= MATRIX_WIDTH; offset += SWICTH_ANIM_STEP)
      {
        displayManager->clear();

        // 绘制旧画面的剩余部分（向右移动）
        // 旧画面从左侧滑出（x坐标从0变为负偏移）
        displayManager->DrawBitmapRawRGB(-offset, 0, oldLeds);

        // 新画面从右侧滑入（x坐标从矩阵宽度变为0）
        displayManager->DrawBitmapRawRGB(MATRIX_WIDTH - offset, 0, newLeds);

        // 更新显示
        displayManager->show();
        delay(25);
      }
      return;
    }
#endif
  }

  mode_select(m);
}
